package org.jingle.sketch.component
{
	import flash.display.Sprite;
	import flash.events.MouseEvent;
	
	import org.cove.ape.Vector;
	import org.jingle.sketch.Anchor;
	import org.jingle.sketch.core.Anchorable;
	import org.jingle.sketch.core.Pickable;
	import org.jingle.sketch.event.AnchorDraggedEvent;
	import org.jingle.sketch.event.AnchorEvent;
	import org.jingle.sketch.utils.Filters;
	
	public class Composite implements Pickable, Anchorable
	{
		/**
		 * position of the composite
		 */
		private var _origin: Point;
		
		/**
		 * offset with last position when composite moved 
		 */
		private var _delta: Point;
		
		/**
		 * transparency of composite
		 */
		private var _alpha:Number = 1;
		
		/**
		 * if background enabled.
		 */
		private var _backgroundEnable:Boolean = true;
		
		/**
		 * take effect when {@code backgroundEnable} is true
		 */ 
		private var _backgroundColor:uint = 0xFFFFFF;
		
		/**
		 * take effect when {@code backgroundEnable} is true
		 * if both background color and image are set, image has the higher priority.
		 */
		private var _backgourndImage:String;
		
		/**
		 * if enable drag.
		 */
		private var _dragEnable:Boolean;

		/**
		 * internal flag to recognize the composite initialized or not.
		 * Just to avoid drawing composite next time.
		 */
		private var _initialized:Boolean;
		
		/**
		 * children of this composite
		 */
		private var _children:Array = new Array();
		
		/**
		 * anchors of this composite
		 */
		private var _anchors:Array = new Array();
		
		/**
		 * the sprite that present on canvas. 
		 */
		private var _sprite:Sprite;
		
		/**
		 * parent of this composite
		 */
		private var _parent:Composite;
		
		/**
		 * angle of this composite, not caculate in radian
		 * @Example 90 = PI/2
		 */
		private var _angle:Number;
		
		/**
		 * border thickness
		 */		
		private var _thickness:int = 1;
		
		/**
		 * border color
		 */
		private var _lineColor:uint;
		
		/**
		 * fill color
		 * default is unit.MAX_VALUE
		 */
		private var _fillColor:uint = uint.MAX_VALUE;
		
		/**
		 * 
		 */
		private var _oldAlpha:Number = 1;
		
		/**
		 * 
		 */
		private var _pickable:Boolean = false;
		
		public function Composite(parent:Composite, container:Sprite = null)
		{
			this._parent = parent;
			this._sprite = new Sprite();
			
			if(parent != null){
				parent.sprite.addChild(_sprite);
				parent.addChild(this);
			}else{
				if(container == null){
					
				}else {
					container.addChild(_sprite);
				}
			}
		}
		
		public function init():void {
			
		}
		
		public function initMouseOverEvents():void {
			sprite.addEventListener(MouseEvent.MOUSE_OVER, onMouseOver);
			sprite.addEventListener(MouseEvent.MOUSE_OUT, onMouseOut);
		}
		
		public function onMouseOver(evt:MouseEvent):void {
			sprite.alpha = this._oldAlpha - 0.2;
		}
		
		public function onMouseOut(evt:MouseEvent):void {
			sprite.alpha = this._oldAlpha;
		}
		
		public function addChild(c:Shape):void {
			this.sprite.addChild(c.sprite);
			_children.push(c);
		}
		
		public function removeChild(c:Shape):void {
			this.sprite.removeChild(c.sprite);
			_children.splice(_children.indexOf(c), 1);
		}
		
		public function removeAllChildren():void {
			var c:Shape;
			for each(c in _children){
				this.sprite.removeChild(c.sprite);
			}
			_children.splice(0, _children.length);
		}

		public function set origin(origin:Point):void {
			this._origin = origin;
		}
		
		public function get origin():Point
		{
			return this._origin;
		}

		protected function mouseDownHandler(e:MouseEvent):void{
			 Sprite(this.sprite).startDrag();
		}
		
		protected function mouseUpHandler(e:MouseEvent):void{
			Sprite(this.sprite).stopDrag();
		}
		
        public function rotate(angle:Number, center:Point):void {
        	super.rotateByAngle(angle, new Vector(center.x, center.y))
        }
        
        public function moveTo(p:Point):void {
        	_delta = p.minus(origin);
        	
        	for (var i:Number=0; i<_children.length; i++){
        		var shape:Shape = _children[i];
        		shape.moveTo(p);
        	}
        	paint();
        }
        
        public function dragEnable(b:Boolean):void {
        	if(b){
        		/*
        		var d:DraggableManager = new DraggableManager(this);
	        	function drag(e:MouseEvent):void {
					d.drag(e);
					//e.stopPropagation();
				}
				
				function drop(e:MouseEvent):void {
					d.drop(e);
					//e.stopPropagation();
				}*/
        		this.sprite.addEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler);
        		this.sprite.addEventListener(MouseEvent.MOUSE_UP, mouseUpHandler);
        	}else{
        		this.sprite.removeEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler);
        		this.sprite.removeEventListener(MouseEvent.MOUSE_UP, mouseUpHandler);
        	}
        	_dragEnable = b;
        	
        	
        }
        
        public function onPicked():void {
        	
        }
        
        public function get shape():Shape {
			return this;
		}
        
        public function getComponentBetween(a0:Anchor, a1:Anchor):Shape {
//        	var shape
//        	for each ()
			return null;		
		}
		
		public function getComponents(anchor:Anchor):Array {
			return null;
		}
        
        public function paint():void {
			if(!initialized){
				init();
			}
			for (var i:Number=0; i<_children.length; i++){
        		var shape:Shape = _children[i];
        		shape.paint();
        	}
		}
		
		public function addEventListener(type:String, handler:Function):void {
			sprite.addEventListener(type, handler);
		}
        
        public function get delta(): Point {
        	return this._delta;
        }
        
        public function set alpha(a:Number):void {
        	this._alpha = a;
        	this._oldAlpha = a;
        }
        
        public function get alpha():Number {
        	return this._alpha;
        }
        
        public function set backgroundColor(color:uint):void {
        	this._backgroundColor = color;
        }
        
        public function get backgroundColor():uint {
        	return this._backgroundColor;
        }
        
        public function get sprite():Sprite {
        	return this._sprite;
        }
        
        public function get parent():Composite {
        	return this._parent;
        }
        
        public function set backgroundEnable(b:Boolean):void {
        	this._backgroundEnable = b;
        }
        
        public function get backgroundEnable():Boolean {
        	return this._backgroundEnable;
        }
        
        public function set backgroundImage(image:String):void {
        	this._backgourndImage = image;
        }
        
        public function get backgroundImage():String {
        	return this._backgourndImage;
        } 
        
        internal function set initialized(b:Boolean):void {
        	this._initialized = b;
        }
        
        internal function get initialized():Boolean {
        	return this._initialized;
        }
        
        public function get angle():Number {
			return this._angle;
		} 

		public function set angle(angle:Number):void {
			this._angle = angle;
		}
        
        public function addAnchor(anchor:Anchor):void {
			if(_anchors == null){
				 _anchors = new Array();
			}
			this._anchors.push(anchor);
		}
		
		public function removeAnchor(anchor:Anchor):void {
			this._anchors.splice(_anchors.indexOf(anchor), 1);
		}
		
		public function get anchors():Array {
			return this._anchors;
		}

		public function addDefaultAnchors():void {} 
		
		
		public virtual function anchorIt(evt:AnchorEvent):Array {
			return null;
		}
		
		public function set thickness(t:int) :void {
			this._thickness = t;
		}
		
		public function get thickness(): int {
			return this._thickness;
		}
		
		public function set lineColor(c:uint): void {
			this._lineColor = c;
		}
		
		public function get lineColor(): uint {
			return this._lineColor;
		}
		
		public function set fillColor(c:uint): void {
			this._fillColor = c;
		}
		
		public function get fillColor(): uint {
			return this._fillColor;
		}
		
		public function set pickable(b:Boolean):void {
			if(b){
				initMouseOverEvents();
			}else{
				sprite.removeEventListener(MouseEvent.MOUSE_OVER, onMouseOver);
				sprite.removeEventListener(MouseEvent.MOUSE_OUT, onMouseOut);
			}
		}
		
		public function addDefaultFilters():void {
			sprite.filters = [Filters.getBevelFilter(), Filters.getDropShadowFilter()];
		}
		
		public function removeFilters():void {
			sprite.filters = [];
		}
		
		public function anchorDragged(evt:AnchorDraggedEvent):void {
			
		}
	}
}